package com.dataex.dbtool;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.nio.ByteBuffer;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.slf4j.LoggerFactory;

public class PgBeanUtil {

	public interface CallBackIntface {
		boolean doTrans(Map<String, Object> outMap, String curKey, Object curObj );
	}
	
	private static final org.slf4j.Logger logger = LoggerFactory	.getLogger(PgBeanUtil.class);
	
	/**
	 * 实现自动 thrifobj 转换到 map<string,object>, 转而转换成json string, 内部过滤 metaDataMap 对象
	 * 
	 * @param thrifObj 
	 * @param call 回调, 可实现部分变量类型转换, 名称转换
	 * @return
	 */
	static public Map<String,Object> ThriftObjToMap( Object thrifObj, boolean bAddNull , @SuppressWarnings("rawtypes") Map<String,Class> typeMap, CallBackIntface call){
		Map<String,Object> inMap = new HashMap<String, Object>();
		Field[] fields = thrifObj.getClass().getDeclaredFields();
		try {
			Object oval = null;
			for (Field field : fields) {
				
				field.setAccessible(true);
				
				//static member, pass
				if ( Modifier.isStatic( field.getModifiers() ))
					continue;
				
				//thrift 内部缓存对象, 过滤掉
				if ( field.getName().equals("metaDataMap") )
					continue;
				oval = null;

				
				//获得对象,执行解析
				Object o = field.get(thrifObj);
				if ( o != null )
					oval = ThriftObjToMap_BaseType( o, bAddNull, typeMap, call );	     
				
				if (typeMap != null )
					typeMap.put(field.getName(), o.getClass());
					
				//数值为 null, bAddNull false, 不生成map中
            	boolean bAdd = true;
            	if ( call != null )
            		bAdd = call.doTrans(inMap, field.getName(), oval);
            	if ( bAdd )
            	{
            		if ( !bAddNull && oval == null )
            			;
            		else
            			inMap.put(field.getName(), oval);	
            	}
			}
		} catch (IllegalArgumentException | IllegalAccessException e) {
			logger.info(""+e);
		}  			
		return inMap;
	}
	
	static public List<Map<String,Object>> ResultSetToMapObj(ResultSet dbO ) throws SQLException{
		if (dbO == null) {
			return null;
		}
 		
		 List<Map<String,Object>> retList = new ArrayList<Map<String,Object>>();
		
	   	 ResultSetMetaData mataD = dbO.getMetaData();
	   	 while ( dbO.next() ){
	   		Map<String,Object> obj = new HashMap<String, Object>();
	 		for ( int i=0; i<mataD.getColumnCount(); i++ )
	 			obj.put(mataD.getColumnName(i+1), dbO.getObject(i+1)); //getobject from 1
	 		retList.add(obj);
	   	 }

		return retList;
	}
	
	/**
	 * 转换子函数, double, string, integer, set, list, map 等作为基本对象处理, 否则按照thrift object 对象处理
	 * @param thrifObj
	 * @param call
	 * @return
	 * @throws IllegalArgumentException
	 * @throws IllegalAccessException
	 */
	static public Object ThriftObjToMap_BaseType( Object thrifObj, boolean bAddNull, @SuppressWarnings("rawtypes") Map<String, Class> typeMap, CallBackIntface call) throws IllegalArgumentException, IllegalAccessException{
		
		Object oval = null;
		
		//普通基本数据类型
        if ( thrifObj.getClass() == Double.class || thrifObj.getClass() == Long.class || thrifObj.getClass() == Byte.class 
        		|| thrifObj.getClass() == String.class  || thrifObj.getClass() == ByteBuffer.class || thrifObj.getClass() == Integer.class ||thrifObj.getClass() == Boolean.class  ){
        	oval = thrifObj;
        }//list 集合对象, 没有子元素递归处理
        else if ( thrifObj instanceof Set<?> ){
        	@SuppressWarnings("unchecked")
			Set<Object> objSet = (Set<Object>) thrifObj;
        	Set<Object> outSet = null;
        	for ( Object j : objSet ){
        		
        		Object o = PgBeanUtil.ThriftObjToMap_BaseType(j, bAddNull, typeMap, call);
        		if ( o == null )
        			continue;
        		
        		if ( outSet == null )
        			outSet = new HashSet<Object>();
        		outSet.add(o);
        	}
        }//list
        else if ( thrifObj instanceof List<?> ){
        	@SuppressWarnings("unchecked")
			List<Object> objList = (List<Object>) thrifObj;
        	List<Object> outList = null;
        	for ( Object j : objList){
        		
        		Object o = PgBeanUtil.ThriftObjToMap_BaseType(j, bAddNull, typeMap, call);
        		if ( o == null )
        			continue;
        		
        		if ( outList == null )
        			outList = new ArrayList<Object>();
       			outList.add(o);
        	}
        	oval = outList;
        }//map
        else if ( thrifObj instanceof Map<?, ?> ){
        	@SuppressWarnings("unchecked")
			Map<Object, Object> objList = (Map<Object, Object>) thrifObj;
        	Map<Object, Object> outMap = null;
        	for ( Map.Entry<Object, Object> en : objList.entrySet() ){
        		Object key = ThriftObjToMap_BaseType(en.getKey(), bAddNull, typeMap, call);
        		Object val = ThriftObjToMap_BaseType(en.getValue(), bAddNull, typeMap, call);
        		if ( outMap == null )
        			outMap = new HashMap<Object, Object>();
        		outMap.put(key, val);
        	}
        	oval = outMap;
        }//发现不是基本类型, 安装 thrift object 对象处理
        else{
        	Map<String,Object> subMap = ThriftObjToMap(thrifObj, bAddNull, typeMap, call);
        	oval = subMap;
        }
		return oval;
	}
			
	static public Object ThriftObjFromMap(Map<String, Object> mapObj, String thriftClass, CallBackIntface call){
	    // 添加两个测试数据。。。
//	    List list = new ArrayList();
//	    list.add(new Bean("张三", "女"));
//	    list.add(new Bean("李四", "男"));
//	    try {
//	        // 遍历集合
//	        for (Object object : list) {
//	            Class clazz = object.getClass();// 获取集合中的对象类型
//	            Field[] fds = clazz.getDeclaredFields();// 获取他的字段数组
//	            for (Field field : fds) {// 遍历该数组
//	                fdname = field.getName();// 得到字段名，
//
//	                metd = clazz.getMethod("get" + change(fdname), null);// 根据字段名找到对应的get方法，null表示无参数
//
//	                if ("name".equals(fdname) && metd != null) {// 比较是否在字段数组中存在name字段，如果不存在短路，如果存在继续判断该字段的get方法是否存在，同时存在继续执行
//	                    Object name = metd.invoke(object, null);// 调用该字段的get方法
//	                    System.out.print("姓名:" + name);// 输出结果
//	                }
//	                if ("sex".equals(fdname) && metd != null) {// 同上
//	                    Object sex = metd.invoke(object, null);
//	                    System.out.println("\t性别:" + sex);
//	                }
//	            }
		return null;
	}
//	
//	static public void main(String[] args){
//		System.out.print("test");
//	}
}
